<?php


namespace App\Zesow\Payment\Wechat;

use App\Events\RechargeSuccessEvent;
use App\Events\TransferSuccessEvent;
use App\Services\Business\Models\UserRedpacketRecord;
use Yansongda\Pay\Pay;
use App\Businesses\BusinessState;
use App\Events\PaymentSuccessEvent;
use Illuminate\Support\Facades\Log;
use App\Exceptions\ServiceException;
use App\Zesow\Payment\Contract\Payment;
use App\Services\Base\Services\CacheService;
use App\Zesow\Payment\Contract\PaymentStatus;
use App\Services\Base\Services\ConfigService;
use App\Services\Order\Services\OrderService;
use App\Services\Base\Interfaces\CacheServiceInterface;
use App\Services\Base\Interfaces\ConfigServiceInterface;
use App\Services\Order\Interfaces\OrderServiceInterface;
use App\Services\Company\Interfaces\CompanyOrderServiceInterface;
use App\Services\Company\Services\CompanyOrderService;


class WechatMini implements Payment
{

    /**
     * @var ConfigService
     */
    protected $configService;
    /**
     * @var OrderService
     */
    protected $orderService;

    /**
     * @var CacheService
     */
    protected $cacheService;
    protected $businessState;

    public function __construct(
        ConfigServiceInterface       $configService,
        OrderServiceInterface        $orderService,
        CacheServiceInterface        $cacheService,
        BusinessState                $businessState
    )
    {
        $this->configService = $configService;
        $this->orderService = $orderService;
        $this->cacheService = $cacheService;
        $this->businessState = $businessState;
    }

    public function create(array $order, array $extra = []): PaymentStatus
    {
        $needPayTotal = $this->businessState->calculateOrderNeedPaidSum($order) * 100;

        try {
            $payOrderData = [
                'out_trade_no' => $order['order_id'],
                'total_fee' => $needPayTotal * 100,
                'body' => $order['order_id'],
                'openid' => $extra['openid'],

            ];

            // 微信支付配置
            $config = $this->configService->getWechatPay();
            $config['notify_url'] = route('payment.callback', ['wechat-mini']);

            // 创建微信支付订单
            $createResult = Pay::wechat($config)->miniapp($payOrderData);

            return new PaymentStatus(true, $createResult);
        } catch (\Exception $exception) {
            exception_record($exception);

            throw new ServiceException(__('system error'));
        }
    }

    public function recharge(array $order, array $extra = []): PaymentStatus
    {
        try {
            $payOrderData = [
                'out_trade_no' => $order['order_id'],
                'description' => '充值会员',
                'amount' => [
                    'total' => $order['charge'] * 100,
                    'currency' => 'CNY',
                ],
                'payer' => [
                    'openid' => $extra['openid'],
                ]
            ];

            // 微信支付配置
            $config = $this->configService->getWechatPay();
            $config['wechat']['default']['notify_url'] = route('payment.callback', ['wechat-mini']);

            // 创建微信支付订单
            $createResult = Pay::wechat($config)->mini($payOrderData);

            return new PaymentStatus(true, $createResult);
        } catch (\Exception $exception) {
            exception_record($exception);

            throw new ServiceException(__('system error'));
        }
    }

    public function query(array $order): PaymentStatus
    {
        return new PaymentStatus(false);
    }

    public function callback()
    {
        $pay = Pay::wechat($this->configService->getWechatPay());
        try {
            $data = $pay->callback();

            if ($data['event_type'] == 'MCHTRANSFER.BATCH.FINISHED') {
                $orderId = $data['resource']['ciphertext']['out_batch_no'];
                $order = UserRedpacketRecord::query()->where('order_id',$orderId)->firstOrFail();
                event(new  TransferSuccessEvent($order->toArray()));

            } elseif ($data['event_type'] == 'TRANSACTION.SUCCESS') {
                $orderId = $data['resource']['ciphertext']['out_trade_no'];
                $order = $this->orderService->findOrFail($orderId);
                if ((substr($orderId, 0, 1) === "r")) {
                    event(new RechargeSuccessEvent($order));
                } else {
                    event(new PaymentSuccessEvent($order));

                }

            }
            return $pay->success();
        } catch (\Exception $e) {
            exception_record($e);
            return $e->getMessage();
        }
    }

    public static function payUrl(array $order): string
    {
        return '';
    }
}
